package com.zyy.game.tianlong.serviceimpl;

import com.zyy.game.tianlong.dto.account.ChangeInfoDto;
import com.zyy.game.tianlong.entity.GamePlayer;
import com.zyy.game.tianlong.entity.Player;
import com.zyy.game.tianlong.network.exception.ServiceException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * @author relufi
 * @date 2019/8/10 0010
 */
@Service
public class AccountServiceImpl {
    private final StringRedisTemplate stringRedisTemplate;
    private final PlayerServiceImpl playerService;
    private static final String REDIS_AUTH_CODE_LOGIN_KEY = "AuthCode::login";
    private static final String REDIS_AUTH_CODE_SIGN_KEY = "AuthCode::sign";
    private static final String REDIS_AUTH_CODE_RESET_KEY = "AuthCode::reset";
    private static final String REDIS_AUTH_CODE_PAY_KEY = "AuthCode::pay";

    public AccountServiceImpl(StringRedisTemplate stringRedisTemplate, PlayerServiceImpl playerService) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.playerService = playerService;
    }

    /**
     * 是否存在这个用户名称的username
     *
     * @param playerName 用户名
     * @return true 存在 false 不存在
     */
    public boolean isExistPlayerName(String playerName) {
        return playerService.existPlayerName(playerName);
    }

    /**
     * 登录手机验证码
     *
     * @param phone 手机号
     */
    public void phoneCodeLoginIn(String phone) {
        phoneCode(phone, true, REDIS_AUTH_CODE_LOGIN_KEY);
    }

    /**
     * 注册手机验证码
     *
     * @param phone 手机号
     */
    public void phoneCodeSignUp(String phone) {
        phoneCode(phone, false, REDIS_AUTH_CODE_SIGN_KEY);
    }

    /**
     * 找回密码手机验证码
     *
     * @param phone 手机号
     */
    public void phoneCodeResetPw(String phone) {
        phoneCode(phone, true, REDIS_AUTH_CODE_RESET_KEY);
    }

    /**
     * 找回密码手机验证码
     *
     * @param phone 手机号
     */
    public void phoneCodePayPw(String phone) {
        phoneCode(phone, true, REDIS_AUTH_CODE_PAY_KEY);
    }

    /**
     * 获取短信验证码
     *
     * @param phone 发送的手机号码
     */
    private void phoneCode(String phone, boolean isLogin, String prefixKey) {
        if (StringUtils.isEmpty(phone) || phone.length() != 11) {
            throw new ServiceException(1, "数据格式错误");
        }
        if (playerService.existPhone(phone)) {
            if (!isLogin) {
                throw new ServiceException(4, "手机号已存在");
            }
        } else {
            if (isLogin) {
                throw new ServiceException(5, "手机号不存在");
            }
        }
//        验证是否超过60秒 重发
        String key = prefixKey + "-exist-" + phone;
        if (stringRedisTemplate.opsForValue().get(key) != null) {
            throw new ServiceException(2, "请在距离上次60秒后再次获取验证码");
        }

        int nextInt = ThreadLocalRandom.current().nextInt(1000000);
        String authCode = Integer.toString(nextInt);
        if (authCode.length() < 6) {
            authCode = String.format("%05d", nextInt);
        }

        //TODO 这里去调用sdk发送验证 现在测试写死123465
        authCode = "123456";
//        添加重发的60秒过期凭证到redis
        stringRedisTemplate.opsForValue().set(key, "1", 60, TimeUnit.SECONDS);
//        添加过期时间为5分钟验证码到redis
        stringRedisTemplate.opsForValue().set(prefixKey + "-" + phone, authCode, 5, TimeUnit.MINUTES);
    }

    /**
     * 通过手机短信验证码的方式 新增玩家
     *
     * @param passWord   密码
     * @param phone      手机号
     * @param playerName 用户名
     * @param authCode   验证码
     */
    public void addPhonePlayer(String passWord, String phone, String playerName, String authCode) {
//        验证数据
        if (StringUtils.isEmpty(passWord) || passWord.length() > 16 || passWord.length() < 3 ||
                StringUtils.isEmpty(phone) || phone.length() != 11 ||
                StringUtils.isEmpty(playerName) || playerName.length() < 2 || playerName.length() > 11 ||
                StringUtils.isEmpty(authCode)) {
            throw new ServiceException(1, "数据格式错误");
        }
//        验证 手机短信验证码
        String key = REDIS_AUTH_CODE_SIGN_KEY + "-" + phone;
        if (!authCode.equals(stringRedisTemplate.opsForValue().get(key))) {
            throw new ServiceException(3, "验证码错误");
        }
        try {
            playerService.addPwdPlayer(passWord, phone, playerName);
        } catch (DuplicateKeyException e) {
            throw new ServiceException(4, "手机号已存在");
        } finally {
            stringRedisTemplate.delete(key);
        }
    }

    /**
     * 微信登录
     *
     * @param openId 微信OpenId
     * @param name   微信名称
     * @param photo  头像
     * @return 玩家
     */
    @Transactional(rollbackFor = Exception.class)
    public Player wxLogin(String openId, String name, String photo) {
        if (StringUtils.isEmpty(openId)) {
            throw new ServiceException(1, "数据格式错误");
        }
        Player player = playerService.getByOpenId(openId);
        if (player != null) {
            return player;
        }
        return playerService.addWxPlayer(openId, name.length() > 11 ? name.substring(0, 11) : name, photo);
    }

    /**
     * 手机号登录
     *
     * @param authCode 验证码
     * @param phone    手机号
     * @return 玩家信息
     */
    public Player phoneLogin(String phone, String authCode) {
        if (StringUtils.isEmpty(phone) || phone.length() != 11 || StringUtils.isEmpty(authCode)) {
            throw new ServiceException(1, "数据格式错误");
        }
        //        验证 手机短信验证码
        String key = REDIS_AUTH_CODE_LOGIN_KEY + "-" + phone;
        if (!authCode.equals(stringRedisTemplate.opsForValue().get(key))) {
            throw new ServiceException(2, "验证码错误");
        }
        return playerService.getByPhone(phone);
    }

    /**
     * 密码登录
     *
     * @param phone    手机号
     * @param passWord 密码
     * @return 玩家信息
     */
    public Player passWordLogin(String phone, String passWord) {
        //        验证数据
        if (StringUtils.isEmpty(passWord) || passWord.length() > 16 || passWord.length() < 3 ||
                StringUtils.isEmpty(phone) || phone.length() != 11) {
            throw new ServiceException(1, "数据格式错误");
        }
        Player player = playerService.getByPhone(phone);
        if (player == null || (!playerService.md5(passWord).equals(player.getPassword()))) {
            throw new ServiceException(6, "账号或密码错误");
        }
        return player;
    }

    /**
     * 重置密码
     *
     * @param phone    手机号
     * @param authCode 验证码
     * @param passWord 新密码
     */
    @Transactional(rollbackFor = Exception.class)
    public void resetPassWord(String phone, String authCode, String passWord) {
        if (StringUtils.isEmpty(passWord) || passWord.length() > 16 || passWord.length() < 3 ||
                StringUtils.isEmpty(authCode)) {
            throw new ServiceException(1, "数据格式错误");
        }
        //        验证 手机短信验证码
        String key = REDIS_AUTH_CODE_RESET_KEY + "-" + phone;
        if (!authCode.equals(stringRedisTemplate.opsForValue().get(key))) {
            throw new ServiceException(2, "验证码错误");
        }
        playerService.resetPassWordByPhone(phone, passWord);
    }

    /**
     * 增加交易密码
     *
     * @param gamePlayer    玩家
     * @param payPassWord 交易密码
     * @param authCode    手机验证码
     */
    public void addPayPassWord(GamePlayer gamePlayer, String payPassWord, String authCode) {
        if (StringUtils.isEmpty(payPassWord) || payPassWord.length() > 16 || payPassWord.length() < 3 ||
                StringUtils.isEmpty(authCode) || gamePlayer.getPlayerId() == null) {
            throw new ServiceException(1, "数据格式错误");
        }
        //        验证 手机短信验证码
        String key = REDIS_AUTH_CODE_PAY_KEY + "-" + gamePlayer.getPhone();
        if (!authCode.equals(stringRedisTemplate.opsForValue().get(key))) {
            throw new ServiceException(2, "验证码错误");
        }
        if (playerService.addPayPassWord(gamePlayer, payPassWord) != 1) {
            throw new ServiceException(11, "已经设置过支付密码了");
        }
    }

    public void addWxPayPassWord(GamePlayer gamePlayer, String payPassWord) {
        Integer playerId = gamePlayer.getPlayerId();
        if (StringUtils.isEmpty(payPassWord) || payPassWord.length() > 16 || payPassWord.length() < 3) {
            throw new ServiceException(1, "数据格式错误");
        }
        if (playerService.addPayPassWord(gamePlayer, payPassWord) != 1) {
            throw new ServiceException(11, "已经设置过支付密码了");
        }
    }

    public void signInReward(GamePlayer gamePlayer) {
        playerService.signInReward(gamePlayer);
    }

    public void changeInfo(ChangeInfoDto changeInfoDto, GamePlayer gamePlayer) {
        Player player = new Player();
        player.setPlayerName(changeInfoDto.getName());
        player.setPhoto(changeInfoDto.getPhoto());
        player.setSignature(changeInfoDto.getSignature());
        playerService.changeInfo(player,gamePlayer);
    }
}
